package com.starblink.imgsearch.camera

import androidx.camera.core.ImageAnalysis.Analyzer
import androidx.camera.core.ImageProxy
import com.google.zxing.BarcodeFormat
import com.google.zxing.BinaryBitmap
import com.google.zxing.DecodeHintType
import com.google.zxing.MultiFormatReader
import com.google.zxing.PlanarYUVLuminanceSource
import com.google.zxing.ReaderException
import com.google.zxing.common.HybridBinarizer
import com.starblink.basic.log.SKLogger
import com.starblink.imgsearch.camera.ui.CameraTVMActivity
import java.util.EnumMap

/**二维码、条形码解析器*/
class QRAnalyzer(private val mActivity: CameraTVMActivity) : Analyzer {
    companion object {
        private const val TAG = "Camera-QRCodeImageAnalyzer"
    }

    private var frameCounter = 0
    private var lastFpsTimestamp = System.nanoTime()

    private val reader = MultiFormatReader()

    /**图片数据对象，复用该对象，减少内存抖动*/
    private var imageData = ByteArray(0)

    init {
        val supportedHints: MutableMap<DecodeHintType, Any> = EnumMap(
            DecodeHintType::class.java
        )
        // 设置支持的条形码二维码格式，目前是所有格式
        supportedHints[DecodeHintType.POSSIBLE_FORMATS] = BarcodeFormat.values().asList()
        reader.setHints(supportedHints)
    }

    override fun analyze(image: ImageProxy) {
//        SKLogger.e(TAG, "analyze, image.width=${image.width}, image.height=${image.height}")
        val plane = image.planes[0]
        val byteBuffer = plane.buffer

        // imageData能够复用，优先复用
        if (imageData.size != byteBuffer.capacity()) {
            imageData = ByteArray(byteBuffer.capacity())
        }
        byteBuffer.get(imageData)

        val source = PlanarYUVLuminanceSource(
            imageData,
            plane.rowStride, image.height,
            0, 0,
            image.width, image.height,
            false
        )

        val binaryBitmap = BinaryBitmap(HybridBinarizer(source))
        reader.reset()
        try {
            reader.decodeWithState(binaryBitmap).text?.let {
                mActivity.onBarcodeScanResultSuccess(it)
            }
        } catch (e: ReaderException) {
            val invertedSource = source.invert()
            val invertedBinaryBitmap = BinaryBitmap(HybridBinarizer(invertedSource))
            reader.reset()
            try {
                reader.decodeWithState(invertedBinaryBitmap).text?.let {
                    mActivity.onBarcodeScanResultSuccess(it)
                }
            } catch (e: ReaderException) {
            }
        }

        // Compute the FPS of the entire pipeline
        val frameCount = 10
        if (++frameCounter % frameCount == 0) {
            frameCounter = 0
            val now = System.nanoTime()
            val delta = now - lastFpsTimestamp
            val fps = 1_000_000_000 * frameCount.toFloat() / delta
            SKLogger.i(TAG, "Analysis FPS: ${"%.02f".format(fps)}")
            lastFpsTimestamp = now
        }

        //!!!资源回收
        image.close()
    }
}
